package org.javaforever.oville.operator;

import org.javaforever.oville.NarrowWord;
import org.javaforever.oville.ValidateException;
import org.javaforever.oville.Word;

public class ClassicOps {
	public static NarrowWord and(NarrowWord val1,NarrowWord val2) throws ValidateException{
		StringBuilder val1Str = new StringBuilder(val1.toBinStr());
		StringBuilder val2Str = new StringBuilder(val2.toBinStr());
		StringBuilder result = new StringBuilder();
		for (int i=0;i<32;i++) {
			char r = bitAnd(val1Str.charAt(i),val2Str.charAt(i));
			result.append(r);
		}
		System.out.println("JerryDebug:and:"+result.toString());
		return NarrowWord.fromBinStr(result.toString());
	}
	
	public static NarrowWord or(NarrowWord val1,NarrowWord val2) throws ValidateException{
		StringBuilder val1Str = new StringBuilder(val1.toBinStr());
		StringBuilder val2Str = new StringBuilder(val2.toBinStr());
		StringBuilder result = new StringBuilder();
		for (int i=0;i<32;i++) {
			char r = bitOr(val1Str.charAt(i),val2Str.charAt(i));
			result.append(r);
		}
		System.out.println("JerryDebug:or:"+result.toString());
		return NarrowWord.fromBinStr(result.toString());
	}
	
	public static NarrowWord xor(NarrowWord val1,NarrowWord val2) throws ValidateException{
		StringBuilder val1Str = new StringBuilder(val1.toBinStr());
		StringBuilder val2Str = new StringBuilder(val2.toBinStr());
		StringBuilder result = new StringBuilder();
		for (int i=0;i<32;i++) {
			char r = bitXor(val1Str.charAt(i),val2Str.charAt(i));
			result.append(r);
		}
		System.out.println("JerryDebug:xor:"+result.toString());
		return NarrowWord.fromBinStr(result.toString());
	}
	
	public static NarrowWord add(NarrowWord val1,NarrowWord val2) throws ValidateException{
		long result = val1.toLong() + val2.toLong();
		return NarrowWord.fromLong(result);
	}
	
	public static NarrowWord not(NarrowWord val1) throws ValidateException{
		StringBuilder val1Str = new StringBuilder(val1.toBinStr());
		StringBuilder result = new StringBuilder();
		for (int i=0;i<32;i++) {
			char r = bitNot(val1Str.charAt(i));
			result.append(r);
		}
		System.out.println("JerryDebug:not:"+result.toString());
		return NarrowWord.fromBinStr(result.toString());
	}
	
	public static char bitAnd(char val1,char val2) throws ValidateException{
		if (val1=='0'&& val2=='0') return '0';
		else if (val1=='0'&& val2=='1') return '0';
		else if (val1=='1'&& val2=='0') return '0';
		else if (val1=='1'&& val2=='1') return '1';		
		else return ' ';
	}
	
	/*
	 * J为进位 10
	 * K为进位 QQ
	 * S为分裂 (0)(1)
	 * L为分裂 (10)(01)
	 */
	public static char bitOr(char val1,char val2) throws ValidateException{
		if (val1=='0'&& val2=='0') return '0';
		else if (val1=='0'&& val2=='1') return '1';		
		else if (val1=='1'&& val2=='0') return '1';
		else if (val1=='1'&& val2=='1') return '1';		
		else return ' ';
	}
	
	/*
	 * J为进位 10
	 * K为进位 QQ
	 * S为分裂 (0)(1)
	 * L为分裂 (10)(01)
	 */
	public static char bitXor(char val1,char val2) throws ValidateException{
		if (val1=='0'&& val2=='0') return '0';
		else if (val1=='0'&& val2=='1') return '1';		
		else if (val1=='1'&& val2=='0') return '1';
		else if (val1=='1'&& val2=='1') return '0';		
		else return ' ';
	}
	
	public static char bitNot(char val1) throws ValidateException{
		if (val1=='0') return '1';
		else if (val1=='1') return '0';
		return ' ';
	}
	
	/*
	 * J为进位 10
	 * K为进位 QQ
	 * S为分裂 (0)(1)
	 * L为分裂 (10)(01)
	 */
	public static char bitAdd(char val1,char val2) throws ValidateException{
		if (val1=='0'&& val2=='0') return '0';
		else if (val1=='0'&& val2=='1') return '1';
		else if (val1=='1'&& val2=='0') return '1';
		else if (val1=='1'&& val2=='1') return 'J';
		else return ' ';
	}
	
	public static NarrowWord parseJChars(String wqs) throws ValidateException{
		return NarrowWord.fromBinStr(wqs);
	}
	
	private static Word replaceSesWithVals(String targetStr, long vals) throws ValidateException {		
		int sCounts = countJ(targetStr);		
		StringBuilder targetSb = new StringBuilder(targetStr);
		String valsStr = longValsToString(vals,sCounts);
		System.out.println("JerryDebug:"+targetStr+":"+vals+":"+sCounts+":"+valsStr);
		if (sCounts>0&&sCounts != valsStr.length()) throw new ValidateException("Unmatch Ses and vals");
		int qpos =0;
		for (int i=0;i<sCounts;i++) {
			for (int j=0;j<targetSb.length();j++) {
				if ('S'== targetSb.charAt(j)) {
					targetSb.replace(j, j+1, ""+valsStr.charAt(qpos));
					qpos++;
				}
			}			
		}
		System.out.println("JerryDebug:"+Word.fromQuadStr(targetSb.toString()));
		return Word.fromQuadStr(targetSb.toString());
	}
	
	private static String longValsToString(long vals, int sCounts) throws ValidateException {
		String retVals = Long.toBinaryString(vals);
		if (sCounts >0 && retVals.length()>sCounts) throw new ValidateException("Unmatch Qs and vals");
		else if (retVals.length()<sCounts) {
			int ceiling = sCounts - retVals.length();
			for (int i=0;i< ceiling;i++) {
				retVals = "0" + retVals;
			}		
		}
		return retVals;
	}
	
	private static int countJ(String wordStr) throws ValidateException{
		int count = 0;
		for (int i=0;i<wordStr.length();i++) {
			if ('J' == wordStr.charAt(i)) {
				count ++;
			}
		}
		return count;
	}
	
	public static void main(String [] args) throws Exception{
		NarrowWord w1 = NarrowWord.fromBinStr("00000000000000000000000000010001");
		NarrowWord w2 = NarrowWord.fromBinStr("10000000000000000000000000000001");
		System.out.println("JerryDebug:Source:w1:"+w1.toBinStr());
		System.out.println("JerryDebug:Source:w2:"+w2.toBinStr());
		NarrowWord result = and(w1,w2);
		System.out.println("JerryDebug:Result:And:"+result.toBinStr());
		
		NarrowWord resultOr = or(w1,w2);
		System.out.println("JerryDebug:Result:Or:");
		System.out.println("JerryDebug:Result:"+resultOr.toBinStr());
		
		NarrowWord r3 = add(w1,w2);
		System.out.println("JerryDebug:Result:add:"+r3.toLong());
		System.out.println(w1.toLong());
		System.out.println(w2.toLong());
		System.out.println(r3.toLong());
	}
}
